home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 8 */
-
- /* FACT.C
-
- Copyright (C) 1990, 1991, 1992, 1993, 1994 by Autodesk, Inc.
-
- Permission to use, copy, modify, and distribute this software in
- object code form for any purpose and without fee is hereby granted,
- provided that the above copyright notice appears in all copies and
- that both that copyright notice and the limited warranty and
- restricted rights notice below appear in all supporting
- documentation.
-
- AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
- AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
- DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
- UNINTERRUPTED OR ERROR FREE.
-
- Use, duplication, or disclosure by the U.S. Government is subject to
- restrictions set forth in FAR 52.227-19 (Commercial Computer
- Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
- (Rights in Technical Data and Computer Software), as applicable.
-
- .
-
- DESCRIPTION:
-
- ADS FACTORIAL application - 3/14/90
- Fancier function tables, and add sqr for illustration - 7/21/90
-
- */
-
- #include <stdio.h>
- #include "adslib.h"
-
- /* Utility definition to get an array's element count (at compile
- time). For example:
-
- int arr[] = {1,2,3,4,5};
- ...
- printf("%d", ELEMENTS(arr));
-
- would print a five. ELEMENTS("abc") can also be used to tell how
- many bytes are in a string constant INCLUDING THE TRAILING NULL. */
-
- #define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
-
-
- /* All the functions that we'll define will be listed in a single table,
- together with the internal function that we call to handle each. The
- functions all take a single argument (the resbuf that has the
- arguments) and return an integer (RTNORM or RTERROR for good or bad
- status). */
-
-
- /* First, define the structure of the table: a string giving the AutoCAD name
- of the function, and a pointer to a function returning type int. */
- struct func_entry { char *func_name; int (*func) _((struct resbuf *)); };
-
- /* Here we declare the functions that handle the calls; at the moment there are
- two of them. */
- int fact _((struct resbuf *rb));
- int squareroot _((struct resbuf *rb));
-
- /* Here we define the array of function names and handlers. */
- static struct func_entry func_table[] = { {/*MSG0*/"fact", fact},
- {/*MSG0*/"sqr", squareroot},
- };
- /* To add more functions to this table, just put them in the list, after
- declaring the function names. Note that in standard C it's all right to
- have a superfluous comma after the last item. */
-
-
- /* The code from here to the end of dofun() is UNCHANGED when you add or delete
- functions. */
-
-
- /* Declarations of other local functions */
- void main _((int, char **));
- int dofun _((void));
- int funcload _((void));
- ads_real rfact _((int x));
- ads_real rsqr _((ads_real x));
-
-
- /*-----------------------------------------------------------------------*/
- /* MAIN - the main routine */
-
- void main(argc,argv)
- int argc;
- char *argv[];
- {
- short scode = RSRSLT; /* Normal result code (default) */
- int stat;
- char errmsg[80];
-
- ads_init(argc, argv); /* Open communication with AutoLISP */
-
- for ( ;; ) { /* Request/Result loop */
-
- if ((stat = ads_link(scode)) < 0) {
- sprintf(errmsg, /*MSG1*/"FACT: bad status from ads_link() = %d\n",
- stat);
- #ifdef Macintosh
- macalert(errmsg);
- #else
- puts(errmsg);
- fflush(stdout);
- #endif /* Macintosh */
- exit(1);
- }
-
- scode = RSRSLT; /* Reset result code */
-
- switch (stat) {
-
- case RQXLOAD: /* Load & define functions */
- scode = funcload() == RTNORM ? RSRSLT : RSERR;
- break;
-
- case RQSUBR: /* Handle external function requests */
- scode = dofun() == RTNORM ? RSRSLT : RSERR;
- break;
-
- default:
- break;
- }
- }
- }
-
- /*-----------------------------------------------------------------------*/
- /* FUNCLOAD -- Define this application's external functions. Return
- RTERROR on error, else RTNORM. */
-
- static int funcload()
- {
- int i;
-
- for (i = 0; i < ELEMENTS(func_table); i++) {
- if (!ads_defun(func_table[i].func_name, i))
- return RTERROR;
- }
- return RTNORM;
- }
-
- /*-----------------------------------------------------------------------*/
- /* DOFUN -- Execute external function (called upon an RQSUBR request).
- Return value from the function executed, RTNORM or RTERROR. */
-
- static int dofun()
- {
- struct resbuf *rb;
- int val;
-
- /* Get the function code and check that it's within range.
- (It can't fail to be, but paranoia doesn't hurt.) */
- if ((val = ads_getfuncode()) < 0 || val >= ELEMENTS(func_table)) {
- ads_fail(/*MSG2*/"Received nonexistent function code.");
- return RTERROR;
- }
-
- /* Fetch the arguments, if any. */
- rb = ads_getargs();
-
- /* Call the handler and return its success-failure status. */
- val = (*func_table[val].func)(rb);
- ads_relrb(rb);
- return val;
- }
-
-
- /* The code from the beginning of main() to here is UNCHANGED when you add or
- delete functions. */
-
- /*-----------------------------------------------------------------------*/
- /* FACT -- First set up the argument, then call the factorial function */
- static int
- fact(rb)
- struct resbuf *rb;
- {
- int x;
-
- if (rb == NULL)
- return RTERROR;
-
- if (rb->restype == RTSHORT) {
- x = rb->resval.rint; /* Save in local variable */
- } else {
- ads_fail(/*MSG3*/"Argument should be an integer.");
- return RTERROR;
- }
-
- if (x < 0) { /* Check argument range */
- ads_fail(/*MSG4*/"Argument should be positive.");
- return RTERROR;
- } else if (x > 170) { /* Avoid floating-point overflow */
- ads_fail(/*MSG5*/"Argument should be 170 or less.");
- return RTERROR;
- }
-
- ads_retreal(rfact(x)); /* Call the function itself, and
- return the value to AutoLISP */
- return RTNORM;
- }
-
- /*-----------------------------------------------------------------------*/
- /* This is the implementation of the actual external factorial function */
-
- static ads_real rfact(n)
- int n;
- {
- ads_real ans = 1.0;
-
- while (n)
- ans *= n--;
-
- return ans;
- }
-
- /*-----------------------------------------------------------------------*/
- /* SQUAREROOT -- First set up the argument, then call the root function */
- static int
- squareroot(rb)
- struct resbuf *rb;
- {
- ads_real x;
-
- if (rb == NULL)
- return RTERROR; /* A proper error msg would be better */
-
- if (rb->restype == RTSHORT) { /* Save in local variable */
- x = (ads_real) rb->resval.rint;
- } else if (rb->restype == RTREAL) {
- x = rb->resval.rreal; /* Can accept either real
- or integer */
- } else {
- ads_fail(/*MSG6*/"Argument should be a real or integer value.");
- return RTERROR;
- }
-
- if (x < 0) { /* Check argument range */
- ads_fail(/*MSG7*/"Argument should be positive.");
- return RTERROR;
- }
-
- ads_retreal(rsqr(x)); /* Call the function itself, and
- return the value to AutoLISP */
-
- return RTNORM;
- }
-
- /*-----------------------------------------------------------------------*/
- /* This is the implementation of the actual external function */
-
- static ads_real rsqr(x) /* Square root by Newton's method */
- ads_real x;
- {
- int n = 50;
- ads_real y, c, cl;
-
- if (x == 0.0) {
- return 0.0;
- }
-
- y = (x * 2 + .1) / (x + 1.0);
- c = (y - x / y) / 2;
- cl= 0.0;
-
- while ((c != cl) && (n-- > 0)) {
- y -= c;
- cl = c;
- c = (y - x / y) / 2;
- }
- return y;
- }
-